﻿
Public Class CTokenParcerTreeRoot
    Inherits CTokenParcerBase

    Protected mobjTokenFactory As ITokenFactory
    Protected mcllChildArr As CTokenParcerBase()
    Protected mnumParcePosBeg As Int32
    Protected mnumParcerChlRankMin As Int32
    Protected mblnAllowTextTail As Boolean
    Protected mblnMustOccureChild As Boolean

    Sub New(cllParceTreeArr_i As CTokenParcerBase(), numParcePosBeg_i As Int32, blnAllowTextTail_i As Boolean, ByVal numParcerChlRankMin_i As Int32, objTokenFactory_i As ITokenFactory)
        mobjTokenFactory = objTokenFactory_i
        mcllChildArr = cllParceTreeArr_i
        mnumParcePosBeg = numParcePosBeg_i
        mblnAllowTextTail = blnAllowTextTail_i
        mnumParcerChlRankMin = numParcerChlRankMin_i
    End Sub

    Sub New(cllParceTreeArr_i As CTokenParcerBase(), numParcePosBeg_i As Int32, ByVal numParcerChlRankMin_i As Int32, objTokenFactory_i As ITokenFactory)
        mobjTokenFactory = objTokenFactory_i
        mcllChildArr = cllParceTreeArr_i
        mnumParcePosBeg = numParcePosBeg_i
        mblnAllowTextTail = False
        mnumParcerChlRankMin = numParcerChlRankMin_i
    End Sub

    Sub New(cllParceTreeArr_i As CTokenParcerBase(), objTokenFactory_i As ITokenFactory)
        mobjTokenFactory = objTokenFactory_i
        mcllChildArr = cllParceTreeArr_i
        mnumParcePosBeg = 0
        mblnAllowTextTail = False
        mnumParcerChlRankMin = Int32.MinValue
    End Sub

    Protected Overrides ReadOnly Property Impl_ChildEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return mcllChildArr
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureChild As Boolean
        Get
            Return mblnMustOccureChild
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureNext As Boolean
        Get
            Return False
        End Get
    End Property

    Protected Overrides ReadOnly Property Impl_NextEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return Nothing
        End Get
    End Property

    Public ReadOnly Property AllowTextTail As Boolean
        Get
            Return mblnAllowTextTail
        End Get
    End Property

    Public ReadOnly Property ParcerChlRankMin As Int32
        Get
            Return mnumParcerChlRankMin
        End Get
    End Property

    Public Overrides ReadOnly Property ParcerType As ETokenParcerType
        Get
            Return ETokenParcerType.Std
        End Get
    End Property

    Public Overridable Property ChildCll As CTokenParcerBase()
        Get
            Return mcllChildArr
        End Get
        Set(cll_i As CTokenParcerBase())
            mcllChildArr = cll_i
        End Set
    End Property

    Protected Overrides ReadOnly Property Impl_TokenFactory As ITokenFactory
        Get
            Return mobjTokenFactory
        End Get
    End Property

    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        numPosCurr_io = mnumParcePosBeg
        numRank_o = mnumParcerChlRankMin
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As CTokenBase)
        If Not mblnAllowTextTail _
        AndAlso numPosCurr_io < strTextRaw_i.Length Then
            Throw New XWackyParceError("Unexected char.", numPosCurr_io)
        End If

        objToken_o = mobjTokenFactory.NewToken(strTextRaw_i, mnumParcePosBeg, CUInt(numPosCurr_io - mnumParcePosBeg), Nothing)
    End Sub

End Class

Public Class CTokenParcerFwdWalker
    Inherits CTokenParcerWhiteSpaceBase

    Protected mnumRank As Int32
    Protected mnumStep As Int32

    Sub New(numRank_i As Int32, numStep_i As Int32)
        If numStep_i <= 0 Then
            Throw New ArgumentOutOfRangeException("numStep_i")
        End If

        mnumRank = numRank_i
        mnumStep = numStep_i
    End Sub

    Sub New(numRank_i As Int32)
        mnumRank = numRank_i
        mnumStep = 1
    End Sub

    Public Property StepSize As Int32
        Get
            Return mnumStep
        End Get
        Set(num_i As Int32)
            If num_i <= 0 Then
                Throw New ArgumentOutOfRangeException("StepSize")
            End If

            mnumStep = num_i
        End Set
    End Property

    Public ReadOnly Property Rank As Int32
        Get
            Return mnumRank
        End Get
    End Property

    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        numRank_o = mnumRank
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_io As CTokenBase)
        numPosCurr_io += mnumStep
    End Sub
End Class

Public MustInherit Class CTokenParcerWhiteSpaceBase
    Inherits CTokenParcerBase

    Protected NotOverridable Overrides ReadOnly Property Impl_ChildEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return Nothing
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureChild As Boolean
        Get
            Return False
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureNext As Boolean
        Get
            Return False
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_NextEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return Nothing
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_TokenFactory As ITokenFactory
        Get
            Return Nothing
        End Get
    End Property

    Public NotOverridable Overrides ReadOnly Property ParcerType As ETokenParcerType
        Get
            Return ETokenParcerType.WhiteSpace
        End Get
    End Property
End Class

Public Class CTokenParcerStdBase
    Inherits CTokenParcerBase

    Private menmType As ETokenParcerType
    Private mobjTokenFactory As ITokenFactory
    Protected mcllParcerNext As NSCllG.ICollection(Of CTokenParcerBase)

    Protected mnumRank As Int32

    Protected mblnMustOccureNext As Boolean

    Protected Sub ParcerNextSet(ByVal cll_i As NSCllG.ICollection(Of CTokenParcerBase))
        mcllParcerNext = cll_i
    End Sub

    Protected Function CanCreateToken() As Boolean
        Return menmType = ETokenParcerType.Std
    End Function

    Protected Sub TokenCreate(strTextRaw_i As String, numPosBeg_i As Int32, numLength_i As UInt32, strTextParced_i As String, ByRef objToken_o As CTokenBase)
        objToken_o = mobjTokenFactory.NewToken(strTextRaw_i, numPosBeg_i, numLength_i, strTextParced_i)
    End Sub

    Protected Sub TokenCreateSafe(strTextRaw_i As String, numPosBeg_i As Int32, numLength_i As UInt32, strTextParced_i As String, ByRef objToken_o As CTokenBase)
        If menmType = ETokenParcerType.Std Then
            objToken_o = mobjTokenFactory.NewToken(strTextRaw_i, numPosBeg_i, numLength_i, strTextParced_i)
        End If
    End Sub

    Protected Sub ParcerTypeSet(ByVal enmType_i As ETokenParcerType, ByVal objTokenFactory_i As ITokenFactory)
        Select Case enmType_i
            Case ETokenParcerType.WhiteSpace
                mcllParcerNext = Nothing
                mblnMustOccureNext = False
                mobjTokenFactory = Nothing
            Case ETokenParcerType.Delimeter
                mobjTokenFactory = Nothing
            Case ETokenParcerType.Std
                If objTokenFactory_i Is Nothing Then
                    Throw New ArgumentNullException("objTokenFactory_i")
                End If

                mobjTokenFactory = objTokenFactory_i
        End Select

        menmType = enmType_i
    End Sub

    Protected Shared Function TokenParcerCllCopy(ByVal cll_i As NSCllG.ICollection(Of CTokenParcerBase)) As CTokenParcerBase()
        If cll_i Is Nothing Then Return Nothing

        TokenParcerCllCopy = Nothing
        Array.Resize(TokenParcerCllCopy, cll_i.Count)
        cll_i.CopyTo(TokenParcerCllCopy, 0)
    End Function

    Protected Sub New(objSeed As CTokenParcerStdBase)
        With objSeed
            menmType = .menmType
            mobjTokenFactory = .mobjTokenFactory
            mnumRank = .mnumRank
            mcllParcerNext = TokenParcerCllCopy(.mcllParcerNext)
            mblnMustOccureNext = .mblnMustOccureNext
        End With
    End Sub

    Protected Sub New(numRank_i As Int32)
        menmType = ETokenParcerType.Delimeter
        mobjTokenFactory = Nothing
        mnumRank = numRank_i
        mcllParcerNext = Nothing
        mblnMustOccureNext = False
    End Sub

    Protected Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType)
        menmType = CType(enmType_i, ETokenParcerType)
        mobjTokenFactory = Nothing
        mnumRank = numRank_i
        mcllParcerNext = Nothing
        mblnMustOccureNext = False
    End Sub

    Protected Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory)
        If objTokenFactory_i Is Nothing Then
            menmType = ETokenParcerType.Delimeter
        Else
            menmType = ETokenParcerType.Std
        End If

        mobjTokenFactory = objTokenFactory_i
        mnumRank = numRank_i
        mcllParcerNext = Nothing
        mblnMustOccureNext = False
    End Sub

    Public Property IsWhiteSpace As Boolean
        Get
            Return menmType = ETokenParcerType.WhiteSpace
        End Get
        Set(bln_i As Boolean)
            If bln_i Then
                mcllParcerNext = Nothing
                mblnMustOccureNext = False
                menmType = ETokenParcerType.WhiteSpace
            Else
                menmType = ETokenParcerType.Delimeter
            End If
        End Set
    End Property

    Public NotOverridable Overrides ReadOnly Property ParcerType As ETokenParcerType
        Get
            Return menmType
        End Get
    End Property

    Protected Overrides ReadOnly Property Impl_TokenFactory As ITokenFactory
        Get
            Return mobjTokenFactory
        End Get
    End Property

    Protected Overrides ReadOnly Property Impl_ChildEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return Nothing
        End Get
    End Property

    Protected Overrides ReadOnly Property Impl_MustOccureChild As Boolean
        Get
            Return False
        End Get
    End Property

    Public Overridable Property MustOccureNext As Boolean
        Get
            Return mblnMustOccureNext
        End Get
        Set(bln_i As Boolean)
            If menmType = ETokenParcerType.WhiteSpace Then
                Throw New InvalidOperationException("Whitespace parce can not have followed ""next"" parcers.")
            End If

            mblnMustOccureNext = bln_i
        End Set
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_NextEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return CType(mcllParcerNext, NSCllG.IEnumerable(Of ITokenParcerTreeNode))
        End Get
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureNext As Boolean
        Get
            Return mblnMustOccureNext
        End Get
    End Property

    Public Property NextCll As NSCllG.ICollection(Of CTokenParcerBase)
        Get
            Return mcllParcerNext
        End Get
        Set(cll_i As NSCllG.ICollection(Of CTokenParcerBase))
            If menmType = ETokenParcerType.WhiteSpace Then
                Throw New InvalidOperationException("Whitespace parce can not have followed ""next"" parcers.")
            End If

            mcllParcerNext = cll_i
        End Set
    End Property

    Public ReadOnly Property Rank As Int32
        Get
            Return mnumRank
        End Get
    End Property

    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        Throw New NotImplementedException()
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As CTokenBase)
        Throw New NotImplementedException()
    End Sub
End Class

Public Class CTokenParcerComplexBase
    Inherits CTokenParcerStdBase

    Protected mblnMustOccureChild As Boolean
    Protected mcllParcerChild As NSCllG.ICollection(Of CTokenParcerBase)


    Protected Sub New(objSeed As CTokenParcerComplexBase)
        MyBase.New(objSeed)

        With objSeed
            mcllParcerChild = TokenParcerCllCopy(.mcllParcerChild)
            mblnMustOccureChild = .mblnMustOccureChild
        End With
    End Sub


    Protected Sub New(numRank_i As Int32)
        MyBase.New(numRank_i)
        mcllParcerChild = Nothing
        mblnMustOccureChild = False
    End Sub

    Protected Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory)
        MyBase.New(numRank_i, objTokenFactory_i)
        mcllParcerChild = Nothing
        mblnMustOccureChild = False
    End Sub

    Public Overridable Property ChildCll As NSCllG.ICollection(Of CTokenParcerBase)
        Get
            Return mcllParcerChild
        End Get
        Set(cll_i As NSCllG.ICollection(Of CTokenParcerBase))
            mcllParcerChild = cll_i
        End Set
    End Property

    Protected Overrides ReadOnly Property Impl_ChildEnum As NSCllG.IEnumerable(Of ITokenParcerTreeNode)
        Get
            Return CType(mcllParcerChild, NSCllG.IEnumerable(Of ITokenParcerTreeNode))
        End Get
    End Property

    Public Overridable Property MustOccureChild As Boolean
        Get
            Return mblnMustOccureChild
        End Get
        Set(iV As Boolean)
            mblnMustOccureChild = iV
        End Set
    End Property

    Protected NotOverridable Overrides ReadOnly Property Impl_MustOccureChild As Boolean
        Get
            Return mblnMustOccureChild
        End Get
    End Property
End Class

Public Class CTokenFactoryStd
    Implements ITokenFactory

    Protected mnumId As Int32

    Public Overridable ReadOnly Property TokenId As Int32
        Get
            Return mnumId
        End Get
    End Property

    Public Overridable Function NewDesigner(strTextRaw_i As String, numPosBeg_i As Integer) As CTokenDesignerBase Implements ITokenFactory.NewDesigner
        Return New CTokenDesignerStd(strTextRaw_i, numPosBeg_i, mnumId)
    End Function

    Public Overridable Function NewToken(strTextRaw_i As String, numPosBeg_i As Integer, numLength_i As UInt32, strTextParced_i As String) As CTokenBase Implements ITokenFactory.NewToken
        If strTextParced_i Is Nothing Then
            Return New CTokenStd(mnumId, numPosBeg_i, numLength_i, strTextRaw_i.Substring(numPosBeg_i, CInt(numLength_i)))
        Else
            Return New CTokenStd(mnumId, numPosBeg_i, numLength_i, strTextParced_i)
        End If
    End Function

    Public Sub New(ByVal numTokenId_i As Int32)
        mnumId = numTokenId_i
    End Sub

    Public Sub New()
        mnumId = 0
    End Sub
End Class

Public Class CTokenParcerFwdWalkerWFilter
    Inherits CTokenParcerFwdWalker

    Private mcllChrIllegalSortedArr As Char()
    Protected mblnThrowOnChrIllegal As Boolean

    Protected Sub CharExcludedCllSet(cll_i As NSCllG.ICollection(Of Char))
        If cll_i Is Nothing Then
            Array.Resize(mcllChrIllegalSortedArr, 0)
        End If

        Dim cllArr As Char() = Nothing
        Array.Resize(cllArr, cll_i.Count)
        cll_i.CopyTo(cllArr, 0)
        Array.Sort(cllArr)
        mcllChrIllegalSortedArr = cllArr
    End Sub

    Sub New(numRank_i As Int32, numStep_i As Int32, ByVal cllCharIllegal_i As NSCllG.ICollection(Of Char))
        MyBase.New(numRank_i, numStep_i)

        CharExcludedCllSet(cllCharIllegal_i)
    End Sub

    Sub New(numRank_i As Int32, ByVal cllCharIllegal_i As NSCllG.ICollection(Of Char))
        MyBase.New(numRank_i)

        CharExcludedCllSet(cllCharIllegal_i)
    End Sub

    Public Property ChrIllegalCll As NSCllG.ICollection(Of Char)
        Get
            Return Array.AsReadOnly(mcllChrIllegalSortedArr)
        End Get
        Set(cll_i As NSCllG.ICollection(Of Char))
            CharExcludedCllSet(cll_i)
        End Set
    End Property

    Public Property ThrowOnChrIllegal As Boolean
        Get
            Return mblnThrowOnChrIllegal
        End Get
        Set(bln_i As Boolean)
            mblnThrowOnChrIllegal = bln_i
        End Set
    End Property

    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        If Array.BinarySearch(mcllChrIllegalSortedArr, strTextRaw_i.Chars(numPosCurr_io)) < 0 Then
            numRank_o = mnumRank
        ElseIf mblnThrowOnChrIllegal Then
            Throw New XWackyParceError("Illegal char.", numPosCurr_io)
        End If
    End Sub
End Class

<FlagsAttribute()> _
Public Enum EPrefixSuffixBehavior
    None = 0
    SuffixExcludeFromToken = 1
    PrefixExcludeFromToken = 2
    BothExcludeFromToken = PrefixExcludeFromToken Or SuffixExcludeFromToken
    DontMovePosAboveSuffix = 4
End Enum
